package scales.utils.collection
import collection.{IndexedSeqOptimized, IndexedSeqLike, IndexedSeq}
import collection.mutable.Builder
import collection.generic.{CanBuildFrom, GenericTraversableTemplate, SeqFactory, GenericCompanion}
import scales.utils.collection.array._
object ImmutableArrayProxyBuilder {
final val vectorAfter = 31
}
case class ImmutableArrayProxyBuilder[ A ]() extends Builder[A, ImmutableArrayProxy[A]]{
import ImmutableArrayProxyBuilder._
private[this] var arrayBuilder = new ImmutableArrayBuilder[A]()
private[this] var vectorBuilder : Builder[A,scala.collection.immutable.Vector[A]] = _
private[this] var inVector = false
private[this] var haveChosen = false
private[this] var canReuse = true
private[this] var length = 0
override def sizeHint( size : Int ) {
if (size > vectorAfter) {
inVector = true
haveChosen = true
if (vectorBuilder eq null) {
vectorBuilder = Vector.newBuilder[A]
}
}
if (inVector) {
vectorBuilder.sizeHint(size)
} else {
arrayBuilder.sizeHint(size)
}
}
@inline final protected def checkVB() {
if (!inVector) {
if (length > vectorAfter) {
moveToVector
}
}
}
protected def moveToVector() {
val r = arrayBuilder.result
if (vectorBuilder eq null) {
vectorBuilder = Vector.newBuilder[A]
}
vectorBuilder.sizeHint(r.len)
vectorBuilder.++=(r)
arrayBuilder.clear
inVector = true
haveChosen = true
}
def result : ImmutableArrayProxy[A] =
if (inVector) VectorImpl(vectorBuilder.result)
else {
val buf = arrayBuilder.buf
import scala.annotation.switch
(length : @switch) match {
case 0 =>
ImmutableArrayProxy.emptyImmutableArray.asInstanceOf[ImmutableArrayProxy[A]]
case 1 =>
IAOne(buf(0).asInstanceOf[A])
case 2 =>
IATwo(buf(0).asInstanceOf[A], buf(1).asInstanceOf[A])
case 3 =>
IAThree(buf(0).asInstanceOf[A], buf(1).asInstanceOf[A], buf(2).asInstanceOf[A])
case _ => {
canReuse = false
if (length != 0 && length == buf.length)
ImmutableArrayAll[A](buf)
else
arrayBuilder.result
}
}
}
override def ++=(xs: TraversableOnce[A]): this.type = {
if (!haveChosen && xs.isInstanceOf[VectorImpl[A]]) {
inVector = true
haveChosen = true
if (vectorBuilder eq null) {
vectorBuilder = Vector.newBuilder[A]
}
}
xs match {
case p : ImmutableArrayProxy[A] =>
if (inVector)
vectorBuilder.++=(p.ar)
else
arrayBuilder.++=(p.ar)
case _ =>
if (inVector)
vectorBuilder.++=(xs)
else
arrayBuilder.++=(xs)
}
length += xs.size
checkVB
this
}
def +=( elem : A) : this.type = {
length += 1
if (inVector) {
vectorBuilder.+=(elem)
this
} else {
arrayBuilder.+=(elem)
checkVB
this
}
}
def clear() {
if (inVector) {
vectorBuilder.clear
}
if (!canReuse) {
arrayBuilder = new ImmutableArrayBuilder[A]()
} else {
arrayBuilder.clear
}
inVector = false
haveChosen = false
canReuse = true
length = 0
}
}
trait ImmutableArrayProxy[+A] extends IndexedSeq[A] with IndexedSeqOptimized[A, ImmutableArrayProxy[A]] with GenericTraversableTemplate[A, ImmutableArrayProxy] {
@inline override def companion: GenericCompanion[ImmutableArrayProxy] = ImmutableArrayProxy
override protected[this] def newBuilder: Builder[A, ImmutableArrayProxy[A]] = ImmutableArrayProxy.newBuilder[A]
def ar : TraversableOnce[A]
}
object ImmutableArrayProxy extends SeqFactory[ImmutableArrayProxy] {
val emptyImmutableArray = IAEmpty[Nothing]()
def one[A](a: A): ImmutableArrayProxy[A] = IAOne(a)
@inline final override def empty[ A ] : ImmutableArrayProxy[A] = emptyImmutableArray.asInstanceOf[ImmutableArrayProxy[A]]
@inline def newBuilder[A]
: Builder[A, ImmutableArrayProxy[A]] =
ImmutableArrayProxyBuilder()
@inline implicit def canBuildFrom[T](implicit ma: ClassManifest[T]): CanBuildFrom[ImmutableArrayProxy[_], T, ImmutableArrayProxy[T]] = new ImmutableArrayProxyCBF[T]{ val m = ma }
trait ImmutableArrayProxyCBF[T] extends CanBuildFrom[ImmutableArrayProxy[_], T, ImmutableArrayProxy[T]] {
val m : ClassManifest[T]
def apply(from: ImmutableArrayProxy[_]): Builder[T, ImmutableArrayProxy[T]] = newBuilder
def apply: Builder[T, ImmutableArrayProxy[T]] = newBuilder
}
}